package com.zx.auth.block.service.impl;

import com.zx.auth.block.enums.AuthorizationGrantTypeEnum;
import com.zx.auth.block.enums.ClientAuthenticationMethodEnum;
import com.zx.auth.block.mapstruct.OAuth2ClientMapStructMapper;
import com.zx.auth.block.modle.OAuth2RegisteredClient;
import com.zx.auth.block.param.OAuth2ClientParam;
import com.zx.auth.block.repository.OAuth2RegisteredClientRepository;
import com.zx.auth.block.repository.custom.OAuth2RegisteredClientCustomRepository;
import com.zx.auth.block.service.IOAuth2ClientService;
import com.zx.auth.block.utils.AuthNoUtils;
import com.zx.auth.block.vo.OAuth2RegisteredClientVO;
import com.zx.core.context.TenantContextHolder;
import com.zx.core.page.PageInfo;
import com.zx.core.wrapper.ObjectWrapper;
import com.zx.core.wrapper.PageWrapper;
import com.zx.core.wrapper.ResponseWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * OAuth2客户端管理服务实现类
 * 实现OAuth2客户端的业务逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OAuth2ClientServiceImpl implements IOAuth2ClientService {

    private final OAuth2RegisteredClientRepository clientRepository;
    private final OAuth2RegisteredClientCustomRepository clientCustomRepository;

    /**
     * 创建新的OAuth2客户端
     *
     * @param clientParam 客户端参数
     * @return 创建结果
     */
    @Override
    public ResponseWrapper createClient(OAuth2ClientParam clientParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证客户端认证方法
            if (null != clientParam.getClientAuthenticationMethods() && !clientParam.getClientAuthenticationMethods().isEmpty()) {
                String[] methods = clientParam.getClientAuthenticationMethods().split(",");
                for (String method : methods) {
                    String trimmedMethod = method.trim();
                    ClientAuthenticationMethodEnum methodEnum = ClientAuthenticationMethodEnum.getByValue(trimmedMethod);
                    if (methodEnum == null) {
                        result.fail("传入的客户端认证方法错误: " + trimmedMethod);
                        return result;
                    }
                }
            }

            // 验证授权类型
            if (null != clientParam.getAuthorizationGrantTypes() && !clientParam.getAuthorizationGrantTypes().isEmpty()) {
                String[] types = clientParam.getAuthorizationGrantTypes().split(",");
                for (String type : types) {
                    String trimmedType = type.trim();
                    AuthorizationGrantTypeEnum typeEnum = AuthorizationGrantTypeEnum.getByValue(trimmedType);
                    if (typeEnum == null) {
                        result.fail("传入的授权类型错误: " + trimmedType);
                        return result;
                    }
                }
            }

            // 业务验证 - 检查是否已存在相同客户端ID的客户端
            if (null != clientParam.getClientId() && !clientParam.getClientId().isEmpty()) {
                List<OAuth2RegisteredClient> existingClients = clientCustomRepository.findByClientIdAndTenantId(clientParam.getClientId(), TenantContextHolder.getTenantId());
                if (!existingClients.isEmpty()) {
                    result.fail("已存在相同客户端ID的客户端!");
                    return result;
                }
            }

            OAuth2RegisteredClient client = OAuth2ClientMapStructMapper.INSTANCE.clientParamToClient(clientParam);

            // 使用项目统一的ID生成方法生成客户端ID，不验证传入的ID参数
            client.setId(AuthNoUtils.generateAuthId());

            // 设置客户端ID发放时间
            if (null == client.getClientIdIssuedAt()) {
                client.setClientIdIssuedAt(LocalDateTime.now());
            }

            // 设置租户ID
            client.setTenantId(TenantContextHolder.getTenantId());

            // 保存客户端信息
            clientRepository.save(client);

        } catch (Exception e) {
            log.error("创建客户端时发生错误", e);
            result.fail("创建客户端时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 根据ID获取OAuth2客户端信息
     *
     * @param id 客户端ID
     * @return 客户端信息
     */
    @Override
    public ObjectWrapper<OAuth2RegisteredClientVO> getClientById(String id) {
        ObjectWrapper<OAuth2RegisteredClientVO> result = new ObjectWrapper<>();
        try {
            // 参数验证
            if (null == id || id.isEmpty()) {
                result.fail("客户端ID不能为空!");
                return result;
            }

            // 查询客户端信息
            Optional<OAuth2RegisteredClient> clientOptional = clientRepository.findById(id);
            if (clientOptional.isPresent()) {
                // 转换为VO对象
                OAuth2RegisteredClientVO clientVO = OAuth2ClientMapStructMapper.INSTANCE.clientToClientVO(clientOptional.get());
                result.setData(clientVO);
            }
        } catch (Exception e) {
            log.error("获取客户端信息时发生错误", e);
            result.fail("获取客户端信息时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 分页查询OAuth2客户端列表
     *
     * @param clientParam 客户端参数
     * @return 客户端列表
     */
    @Override
    public PageWrapper<OAuth2RegisteredClientVO> listClients(OAuth2ClientParam clientParam) {
        PageWrapper<OAuth2RegisteredClientVO> result = new PageWrapper<>();

        try {
            // 使用PageInfo帮助类处理分页计算，统一项目中的分页处理逻辑
            PageInfo pageInfo = new PageInfo(clientParam.getPageNum(), clientParam.getPageSize());

            // 创建分页对象
            Pageable pageable = PageRequest.of(
                    pageInfo.getPageNum().intValue(),
                    pageInfo.getPageSize().intValue()
            );

            // 使用自定义仓库进行分页查询
            Page<OAuth2RegisteredClient> clientsByPage = clientCustomRepository.findClientsByPage(clientParam, pageable, TenantContextHolder.getTenantId());

            // 转换为VO对象
            List<OAuth2RegisteredClientVO> voList = clientsByPage.getContent().stream()
                    .map(OAuth2ClientMapStructMapper.INSTANCE::clientToClientVO)
                    .toList();

            // 设置返回结果
            result.setData(voList);
            result.setTotal(clientsByPage.getTotalElements());
            result.setCurrentPageNum(clientParam.getPageNum());
            result.setTotalPage(pageInfo);
        } catch (Exception e) {
            log.error("分页查询客户端时发生错误", e);
            result.fail("分页查询客户端时发生错误: " + e.getMessage());
        }

        return result;
    }

    /**
     * 更新OAuth2客户端信息
     *
     * @param clientParam 更新的客户端参数
     * @return 更新后的客户端信息
     */
    @Override
    public ResponseWrapper updateClient(OAuth2ClientParam clientParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证客户端认证方法
            if (null != clientParam.getClientAuthenticationMethods() && !clientParam.getClientAuthenticationMethods().isEmpty()) {
                String[] methods = clientParam.getClientAuthenticationMethods().split(",");
                for (String method : methods) {
                    String trimmedMethod = method.trim();
                    ClientAuthenticationMethodEnum methodEnum = ClientAuthenticationMethodEnum.getByValue(trimmedMethod);
                    if (methodEnum == null) {
                        result.fail("传入的客户端认证方法错误: " + trimmedMethod);
                        return result;
                    }
                }
            }

            // 验证授权类型
            if (null != clientParam.getAuthorizationGrantTypes() && !clientParam.getAuthorizationGrantTypes().isEmpty()) {
                String[] types = clientParam.getAuthorizationGrantTypes().split(",");
                for (String type : types) {
                    String trimmedType = type.trim();
                    AuthorizationGrantTypeEnum typeEnum = AuthorizationGrantTypeEnum.getByValue(trimmedType);
                    if (typeEnum == null) {
                        result.fail("传入的授权类型错误: " + trimmedType);
                        return result;
                    }
                }
            }

            // 业务验证 - 查询客户端是否存在
            Optional<OAuth2RegisteredClient> existingClientOptional = clientRepository.findById(clientParam.getId());

            if (existingClientOptional.isEmpty()) {
                result.fail("客户端不存在: " + clientParam.getId());
                return result;
            }
            OAuth2RegisteredClient client = OAuth2ClientMapStructMapper.INSTANCE.clientParamToClient(clientParam);
            // 确保租户ID不被修改
            client.setTenantId(TenantContextHolder.getTenantId());
            // 保存更新后的客户端信息
            clientRepository.save(client);
        } catch (Exception e) {
            log.error("更新客户端时发生错误", e);
            result.fail("更新客户端时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 删除OAuth2客户端
     *
     * @param id 客户端ID
     * @return 删除结果
     */
    @Override
    public ResponseWrapper deleteClient(String id) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 业务验证 - 查询客户端是否存在
            Optional<OAuth2RegisteredClient> clientOptional = clientRepository.findById(id);

            if (clientOptional.isEmpty()) {
                result.fail("客户端不存在: " + id);
                return result;
            }

            // 验证租户权限 - 确保只能删除当前租户的数据
            // 虽然查询结果应该是当前租户的数据，但为了安全起见，再次验证
            OAuth2RegisteredClient client = clientOptional.get();

            // 安全比较租户ID，防止跨租户操作
            if (!TenantContextHolder.getTenantId().equals(client.getTenantId())) {
                result.fail("非当前租户的数据，不能删除");
                return result;
            }

            // 删除客户端
            clientRepository.delete(client);
        } catch (Exception e) {
            log.error("删除客户端时发生错误", e);
            result.fail("删除客户端时发生错误: " + e.getMessage());
        }
        return result;
    }
}